﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.Drawing;
using System.Drawing.Text;

namespace VFDDriver.VFD
{
    public class CharMap
    {
        public struct MapItem
        {

            private byte _index;
            /// <summary>TODO: Add description here.</summary>
            public byte Index
            {
                get { return _index; }
                set { _index = value; }
            }


            private byte[] _leds;
            /// <summary>TODO: Add description here.</summary>
            public byte[] Leds
            {
                get { return _leds; }
                set { _leds = value; }
            }

            public MapItem(byte index, byte[] leds)
            {
                _index = index;
                _leds = leds;
            }
        }

        #region Properties

        #region Serial Port

        private SerialPort _serialPort;
        /// <summary>TODO: Add description here.</summary>
        public SerialPort Port
        {
            get { return _serialPort; }
        }

        #endregion

        #region Instance

        static CharMap _instance;

        /// <summary>
        /// Instance of the CharMap.
        /// </summary>
        public static CharMap Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new CharMap();
                return _instance;
            }
        }

        #endregion

        #region Initialized

        private bool _initialized;
        /// <summary>TODO: Add description here.</summary>
        public bool Initialized
        {
            get { return _initialized; }
        }

        #endregion

        private Dictionary<char, MapItem> _charMap;
        private byte _currentCharId = 32;//TODO: Set correct initial value

        #endregion

        #region Constructors

        private CharMap()
        {
            _charMap = new Dictionary<char, MapItem>();
        }

        #endregion

        #region Methods

        public void Initialize(SerialPort port)
        {
            _serialPort = port;

            //_charMap.Add(' ', byte.Parse("20", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('!', byte.Parse("21", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('\"', byte.Parse("22", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('#', byte.Parse("23", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('$', byte.Parse("24", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('%', byte.Parse("25", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('&', byte.Parse("26", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('\'', byte.Parse("27", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('(', byte.Parse("28", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add(')', byte.Parse("29", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('*', byte.Parse("2A", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('+', byte.Parse("2B", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add(',', byte.Parse("2C", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('-', byte.Parse("2D", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('.', byte.Parse("2E", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('/', byte.Parse("2F", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('0', byte.Parse("30", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('1', byte.Parse("31", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('2', byte.Parse("31", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('3', byte.Parse("31", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('4', byte.Parse("31", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('5', byte.Parse("31", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('6', byte.Parse("31", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('7', byte.Parse("31", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('8', byte.Parse("31", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('9', byte.Parse("31", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add(':', byte.Parse("31", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add(';', byte.Parse("31", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('<', byte.Parse("31", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('=', byte.Parse("31", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('>', byte.Parse("31", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('?', byte.Parse("31", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('@', byte.Parse("41", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('A', byte.Parse("41", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('B', byte.Parse("41", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('C', byte.Parse("41", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('D', byte.Parse("41", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('E', byte.Parse("41", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('F', byte.Parse("41", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('G', byte.Parse("41", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('H', byte.Parse("41", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('I', byte.Parse("41", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('J', byte.Parse("41", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('K', byte.Parse("41", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('L', byte.Parse("41", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('M', byte.Parse("41", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('N', byte.Parse("41", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('O', byte.Parse("41", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('P', byte.Parse("51", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('Q', byte.Parse("51", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('R', byte.Parse("51", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('S', byte.Parse("51", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('T', byte.Parse("51", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('U', byte.Parse("51", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('V', byte.Parse("51", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('W', byte.Parse("51", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('X', byte.Parse("51", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('Y', byte.Parse("51", System.Globalization.NumberStyles.HexNumber));
            //_charMap.Add('Z', byte.Parse("51", System.Globalization.NumberStyles.HexNumber));
            //...

        }

        public byte[] GetBytes(string value)
        {
            List<byte> ret = new List<byte>();

            foreach (char c in value)
            {
                lock (_charMap)
                {

                    if (_charMap.ContainsKey(c))
                    {
                        ret.Add(_charMap[c].Index);
                    }
                    else
                    {

                        MapItem item = AddUnknownChar(c);
                        _charMap.Add(c, item);
                        ret.Add(item.Index);
                    }
                }
            }

            return ret.ToArray();
        }


        private MapItem AddUnknownChar(char letter)
        {
            int width = 5;
            int height = 7;
            _currentCharId++;

            List<byte> ret = new List<byte>();

            ret.Add(26);
            ret.Add(_currentCharId);
            if (letter == ' ')
            {
                for (int i = 0; i < height; i++)
                {
                    ret.Add(0);
                }
            }
            else
            {
                using (Bitmap b = new Bitmap(width, height))
                {
                    Font f = new Font("Lucid", 12F);
                    Graphics g = Graphics.FromImage(b);
                    RectangleF canvas = new RectangleF(0, 0, width, height);
                    g.FillRectangle(Brushes.White, canvas);
                    g.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit;
                    g.DrawString(letter.ToString(), f, Brushes.Black, -3, -1);

                    for (int i = 0; i < height; i++)
                    {
                        byte by = 0;
                        for (int j = 0; j < width; j++)
                        {
                            Color c = b.GetPixel(j, i);
                            if (c.ToArgb() == Color.Black.ToArgb())
                            {

                            }
                            else if (c.ToArgb() == Color.White.ToArgb())
                            {
                                by += (byte)Math.Pow(2, (7 - j));
                            }
                            else
                            {
                            }
                        }
                        ret.Add(by);
                    }
                }
                _serialPort.Write(ret.ToArray(), 0, ret.Count);
            }

            ret.RemoveRange(0, 2);
            MapItem mapItem = new MapItem((byte)_currentCharId, ret.ToArray());
            Console.WriteLine("Char " + letter + " - " + mapItem.Index);
            foreach (byte b in mapItem.Leds)
            {
                string val = System.Convert.ToString(b, 2).PadLeft(8, '0');
                Console.Write(val[0] == '1' ? "x" : " ");
                Console.Write(val[1] == '1' ? "x" : " ");
                Console.Write(val[2] == '1' ? "x" : " ");
                Console.Write(val[3] == '1' ? "x" : " ");
                Console.Write(val[4] == '1' ? "x" : " ");
                Console.WriteLine();
            }
            return mapItem;
        }

        #endregion

    }
}
